#pragma once

#include<iostream>
#include<string>
#include<cstring>
#include<cassert>
#include<functional>
#include<pthread.h>

class Thread;

class Context
{
public:
    Thread* this_;
    void* args_;
public:
    Context()
    :this_(nullptr)
    ,args_(nullptr)
    {}
    ~Context()
    {}
};
class Thread
{
public:
    typedef std::function<void*(void*)>func_t;
    const int num = 1024;
public:
    Thread(func_t func,void* args,int number)
    :func_(func)
    ,args_(args)
    {
        char buffer[num];
        snprintf(buffer,sizeof(buffer),"thread-%d",number);
        name_ = buffer;
        Context* ctx = new Context();
        ctx->this_  = this;
        ctx->args_  = args_;
        int n = pthread_create(&tid_,nullptr,start_routine,ctx);
        assert(n == 0);//debug方式时存在, release方式时不存在, 那么n就是一个定义了, 没有被使用的变量
        (void)n;//在有些编译器会有警告,这块就是告诉编译器我用着呢别再报警告
    }
    static void* start_routine(void* args)
    {
        Context* ctx = static_cast<Context*>(args);
        void* ret = ctx->this_->run(ctx->args_);
        delete ctx;
        return ret;
    }
    // void start()
    // {
    //     Context* ctx = new Context();
    //     ctx->this_  = this;
    //     ctx->args_  = args_;
    //     int n = pthread_create(&tid_,nullptr,start_routine,ctx);
    //     assert(n == 0);//debug方式时存在, release方式时不存在, 那么n就是一个定义了, 没有被使用的变量
    //     (void)n;//在有些编译器会有警告,这块就是告诉编译器我用着呢别再报警告
    // }
    void join()
    {
        int n = pthread_join(tid_,nullptr);
        assert(n == 0);
        (void)n;
    }
    void* run(void* args)
    {
        return func_(args);
    }
    ~Thread()
    {

    }
private:
    std::string name_;
    func_t func_;
    void* args_;
    pthread_t tid_;
};